package org.saasplay.resolver;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.saasplay.resource.Group;
import org.saasplay.resource.Resource;
import org.saasplay.resource.ServiceData;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author cuishifeng
 */
public class XmlResolverUtils {

    private static XMLConfiguration configuration;


    public static Map<String, ServiceData> read(String path) throws Exception {

        Document document = getConfiguration(path).getDocument();
        NodeList pageList = document.getElementsByTagName(XmlTagsEnum.PAGE_DATA.name);
        if (pageList.getLength() <= 0) {
            return null;
        }
        Map<String, ServiceData> serviceDataMap = new ConcurrentHashMap<>(16);

        for (int i = 0; i < pageList.getLength(); i++) {
            Node page = pageList.item(i);
            NamedNodeMap attrs = page.getAttributes();
            String pageCode = attrs.getNamedItem(XmlTagsEnum.PAGE_DATA_ATR_CODE.name).getNodeValue();
            ServiceData serviceData = new ServiceData();
            serviceData.getPageData().put(ServiceDataEnum.attr_pageCode.name, pageCode);
            NodeList childNodes = page.getChildNodes();

            for (int k = 0; k < childNodes.getLength(); k++) {
                Node groupNode = childNodes.item(k);
                Group group = new Group();
                NodeList groupChildNodes = groupNode.getChildNodes();

                for (int j = 0; j < groupChildNodes.getLength(); j++) {
                    Node resourceNode = groupChildNodes.item(j);
                    Resource resource = new Resource();
                    NodeList resourceChildNodes = resourceNode.getChildNodes();
                    for (int l = 0; l < resourceChildNodes.getLength(); l++) {
                        Node resourceChild = resourceChildNodes.item(l);
                        if (resourceChild.getNodeType() == Node.ELEMENT_NODE) {
                            resource.getResource().put(resourceChild.getNodeName(), resourceChild.getTextContent());
                        }
                    }

                    if (resourceNode.getNodeType() == Node.ELEMENT_NODE && resourceNode.getNodeName().equals(XmlTagsEnum.RESOURCE_DATA.name)) {
                        NamedNodeMap resourceAttrs = resourceNode.getAttributes();
                        String resourceCode = resourceAttrs.getNamedItem(XmlTagsEnum.RESOURCE_DATA_ATR_CODE.name).getNodeValue();
                        resource.getResource().put(ServiceDataEnum.attr_resourceCode.name, resourceCode);
                        group.getResourceList().add(resource);
                    } else if (resourceNode.getNodeType() == Node.ELEMENT_NODE && !resourceNode.getNodeName().equals(XmlTagsEnum.RESOURCE_DATA.name)) {
                        group.getGroup().put(resourceNode.getNodeName(), resourceNode.getTextContent());
                    }
                }

                if (groupNode.getNodeType() == Node.ELEMENT_NODE && groupNode.getNodeName().equals(XmlTagsEnum.GROUP_DATA.name)) {
                    NamedNodeMap groupAttrs = groupNode.getAttributes();
                    String groupCode = groupAttrs.getNamedItem(XmlTagsEnum.GROUP_DATA_ATR_CODE.name).getNodeValue();
                    group.getGroup().put(ServiceDataEnum.attr_groupCode.name, groupCode);
                    serviceData.getGroupData().add(group);
                } else if (groupNode.getNodeType() == Node.ELEMENT_NODE && !groupNode.getNodeName().equals(XmlTagsEnum.GROUP_DATA.name)) {
                    serviceData.getPageData().put(groupNode.getNodeName(), groupNode.getTextContent());
                }

            }

            serviceDataMap.put(pageCode, serviceData);
        }
        return serviceDataMap;
    }

    public static XMLConfiguration getConfiguration(String url) throws ConfigurationException {
        if (configuration != null) {
            return configuration;
        }
        configuration = new XMLConfiguration(url);
        return configuration;
    }
}
